package com.urbane.gateway.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.IOException;
import java.util.List;

// 全局异常处理器，集中处理所有异常
// 包括运行时异常（RuntimeException 及其子类）、编译时异常（受检异常）以及错误（Error）。
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    // 异常处理参考官方文档 https://docs.springjava.cn/spring-framework/reference/web/webmvc/mvc-controller/ann-exceptionhandler.html
    // 更具体的异常处理器应放在前面

    // 1、以下是运行时异常

    // 空指针异常，当尝试对 null 引用的对象调用方法或访问成员变量时抛出。
    @ExceptionHandler(NullPointerException.class)
    public ResponseEntity<String> handleNullPointerException(NullPointerException ex) {
        log.error("Null pointer exception occurred", ex);
        // return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("A null pointer exception occurred.");
        return ResponseEntity.internalServerError().body("A null pointer exception occurred." + ex.getMessage());
    }

    // 非法参数异常，当传递给方法或构造函数的参数无效时抛出。
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException ex) {
        log.error("Illegal argument exception occurred", ex);
        // return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("An illegal argument exception occurred.");
        return ResponseEntity.badRequest().body("An illegal argument exception occurred." + ex.getMessage());
    }

    // 数组越界异常，当尝试访问数组越界位置的元素时抛出。
    @ExceptionHandler(ArrayIndexOutOfBoundsException.class)
    public ResponseEntity<String> handleArrayIndexOutOfBoundsException(ArrayIndexOutOfBoundsException ex) {
        log.error("Array index out of bounds exception occurred", ex);
        // return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("An array index out of bounds error occurred.");
        return ResponseEntity.badRequest().body("An array index out of bounds error occurred." + ex.getMessage());
    }

    // 2、以下是编译时异常，也就是受检异常
    // 对于受检异常（Checked Exception），虽然编译器要求必须捕获或声明抛出这些异常，但你仍然可以在 @ExceptionHandler 方法中处理它们。这有助于集中管理所有可能发生的异常
    @ExceptionHandler(IOException.class)
    public ResponseEntity<String> handleIOException(IOException ex) {
        log.error("I/O error occurred", ex);
        return ResponseEntity.internalServerError().body(ex.getMessage());
    }

    // 验证失败（如表单提交的数据无效）。
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<String> handleValidationException(MethodArgumentNotValidException ex) {
        List<String> errors = ex.getBindingResult().getFieldErrors().stream()
                .map(error -> error.getField() + ": " + error.getDefaultMessage())
                .toList();
        log.error("Validation error occurred: {}", errors);
        // return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors.toString());
        return ResponseEntity.badRequest().body(errors.toString());
    }

    // 3、通用异常处理器应放在后面
    // 默认异常处理。为了捕捉所有未预见的异常，你可以定义一个通用的异常处理器来处理所有其他类型的异常。这对于防止未处理的异常泄露到客户端非常重要。
    // 如果你定义了一个捕获所有异常的通用处理器（如 @ExceptionHandler(Exception.class)），那么它应该被放置在其他更具体的异常处理器之后。否则，它可能会拦截所有异常，导致更具体的异常处理器无法生效。
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleGenericException(Exception ex) {
        log.error("Unexpected error occurred", ex);
        // return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An unexpected error occurred.");
        return ResponseEntity.internalServerError().body("An unexpected error occurred." + ex.getMessage());
    }

    // 错误处理器
    // 尽管 Error 类及其子类通常表示严重的系统问题，比如内存不足、JVM崩溃等，理论上也可以使用 @ExceptionHandler 来捕获和处理它们。然而，由于这些问题往往是不可恢复的，所以实际应用中很少这样做。
    @ExceptionHandler(Error.class)
    public ResponseEntity<String> handleError(Error ex) {
        log.error("Severe error occurred", ex);
        // return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("A severe error occurred in the application.");
        return ResponseEntity.internalServerError().body("A severe error occurred in the application." + ex.getMessage());
    }

}

// 自定义业务异常：针对你的应用程序特有的业务场景。
// 技术性异常：如数据库、I/O和其他系统级别的异常。
// 运行时异常：如空指针异常、类型转换异常等。
// HTTP相关异常：确保客户端接收到正确的HTTP状态码和错误信息。


// 将更具体的异常处理器放在前面：确保那些针对特定异常类型的方法优先于通用的异常处理器。
// 使用细粒度的异常处理：尽可能为不同的异常类型编写专用的处理逻辑，而不是依赖一个单一的通用处理器来处理所有情况。
// 避免过度捕获：不要轻易地捕获所有异常并隐藏它们，这可能导致难以调试的问题。对于未知或不可预见的异常，最好记录详细的日志信息以便后续分析。

